﻿using System;
using System.Collections;
using System.Collections.Generic;

namespace Priority_Queue
{
	// Token: 0x02000324 RID: 804
	public sealed class FastPriorityQueue<T> : IFixedSizePriorityQueue<T, float>, IPriorityQueue<T, float>, IEnumerable<T>, IEnumerable where T : FastPriorityQueueNode
	{
		// Token: 0x060014AA RID: 5290 RVA: 0x00087F62 File Offset: 0x00086162
		public FastPriorityQueue(int maxNodes)
		{
			this._numNodes = 0;
			this._nodes = new T[maxNodes + 1];
		}

		// Token: 0x17000341 RID: 833
		// (get) Token: 0x060014AB RID: 5291 RVA: 0x00087F86 File Offset: 0x00086186
		public int Count
		{
			get
			{
				return this._numNodes;
			}
		}

		// Token: 0x17000342 RID: 834
		// (get) Token: 0x060014AC RID: 5292 RVA: 0x00087F8E File Offset: 0x0008618E
		public int MaxSize
		{
			get
			{
				return this._nodes.Length - 1;
			}
		}

		// Token: 0x060014AD RID: 5293 RVA: 0x00087F9A File Offset: 0x0008619A
		public void Clear()
		{
			Array.Clear(this._nodes, 1, this._numNodes);
			this._numNodes = 0;
		}

		// Token: 0x060014AE RID: 5294 RVA: 0x00087FB5 File Offset: 0x000861B5
		public bool Contains(T node)
		{
			return this._nodes[node.QueueIndex] == node;
		}

		// Token: 0x060014AF RID: 5295 RVA: 0x00087FDC File Offset: 0x000861DC
		public void Enqueue(T node, float priority)
		{
			node.Priority = priority;
			this._numNodes++;
			this._nodes[this._numNodes] = node;
			node.QueueIndex = this._numNodes;
			this.CascadeUp(this._nodes[this._numNodes]);
		}

		// Token: 0x060014B0 RID: 5296 RVA: 0x00088044 File Offset: 0x00086244
		private void Swap(T node1, T node2)
		{
			this._nodes[node1.QueueIndex] = node2;
			this._nodes[node2.QueueIndex] = node1;
			int queueIndex = node1.QueueIndex;
			node1.QueueIndex = node2.QueueIndex;
			node2.QueueIndex = queueIndex;
		}

		// Token: 0x060014B1 RID: 5297 RVA: 0x000880BC File Offset: 0x000862BC
		private void CascadeUp(T node)
		{
			for (int i = node.QueueIndex / 2; i >= 1; i = node.QueueIndex / 2)
			{
				T t = this._nodes[i];
				if (this.HasHigherPriority(t, node))
				{
					break;
				}
				this.Swap(node, t);
			}
		}

		// Token: 0x060014B2 RID: 5298 RVA: 0x0008811C File Offset: 0x0008631C
		private void CascadeDown(T node)
		{
			int num = node.QueueIndex;
			for (;;)
			{
				T t = node;
				int num2 = 2 * num;
				if (num2 > this._numNodes)
				{
					break;
				}
				T t2 = this._nodes[num2];
				if (this.HasHigherPriority(t2, t))
				{
					t = t2;
				}
				int num3 = num2 + 1;
				if (num3 <= this._numNodes)
				{
					T t3 = this._nodes[num3];
					if (this.HasHigherPriority(t3, t))
					{
						t = t3;
					}
				}
				if (t == node)
				{
					goto IL_D1;
				}
				this._nodes[num] = t;
				int queueIndex = t.QueueIndex;
				t.QueueIndex = num;
				num = queueIndex;
			}
			node.QueueIndex = num;
			this._nodes[num] = node;
			return;
			IL_D1:
			node.QueueIndex = num;
			this._nodes[num] = node;
		}

		// Token: 0x060014B3 RID: 5299 RVA: 0x0008821F File Offset: 0x0008641F
		private bool HasHigherPriority(T higher, T lower)
		{
			return higher.Priority < lower.Priority;
		}

		// Token: 0x060014B4 RID: 5300 RVA: 0x00088240 File Offset: 0x00086440
		public T Dequeue()
		{
			T t = this._nodes[1];
			this.Remove(t);
			return t;
		}

		// Token: 0x060014B5 RID: 5301 RVA: 0x00088264 File Offset: 0x00086464
		public void Resize(int maxNodes)
		{
			T[] array = new T[maxNodes + 1];
			int num = Math.Min(maxNodes, this._numNodes);
			for (int i = 1; i <= num; i++)
			{
				array[i] = this._nodes[i];
			}
			this._nodes = array;
		}

		// Token: 0x17000343 RID: 835
		// (get) Token: 0x060014B6 RID: 5302 RVA: 0x000882B3 File Offset: 0x000864B3
		public T First
		{
			get
			{
				return this._nodes[1];
			}
		}

		// Token: 0x060014B7 RID: 5303 RVA: 0x000882C1 File Offset: 0x000864C1
		public void UpdatePriority(T node, float priority)
		{
			node.Priority = priority;
			this.OnNodeUpdated(node);
		}

		// Token: 0x060014B8 RID: 5304 RVA: 0x000882D8 File Offset: 0x000864D8
		private void OnNodeUpdated(T node)
		{
			int num = node.QueueIndex / 2;
			T lower = this._nodes[num];
			if (num > 0 && this.HasHigherPriority(node, lower))
			{
				this.CascadeUp(node);
			}
			else
			{
				this.CascadeDown(node);
			}
		}

		// Token: 0x060014B9 RID: 5305 RVA: 0x0008832C File Offset: 0x0008652C
		public void Remove(T node)
		{
			if (node.QueueIndex == this._numNodes)
			{
				this._nodes[this._numNodes] = (T)((object)null);
				this._numNodes--;
				return;
			}
			T t = this._nodes[this._numNodes];
			this.Swap(node, t);
			this._nodes[this._numNodes] = (T)((object)null);
			this._numNodes--;
			this.OnNodeUpdated(t);
		}

		// Token: 0x060014BA RID: 5306 RVA: 0x000883C0 File Offset: 0x000865C0
		public IEnumerator<T> GetEnumerator()
		{
			for (int i = 1; i <= this._numNodes; i++)
			{
				yield return this._nodes[i];
			}
			yield break;
		}

		// Token: 0x060014BB RID: 5307 RVA: 0x000883DB File Offset: 0x000865DB
		IEnumerator IEnumerable.GetEnumerator()
		{
			return this.GetEnumerator();
		}

		// Token: 0x060014BC RID: 5308 RVA: 0x000883E4 File Offset: 0x000865E4
		public bool IsValidQueue()
		{
			for (int i = 1; i < this._nodes.Length; i++)
			{
				if (this._nodes[i] != null)
				{
					int num = 2 * i;
					if (num < this._nodes.Length && this._nodes[num] != null && this.HasHigherPriority(this._nodes[num], this._nodes[i]))
					{
						return false;
					}
					int num2 = num + 1;
					if (num2 < this._nodes.Length && this._nodes[num2] != null && this.HasHigherPriority(this._nodes[num2], this._nodes[i]))
					{
						return false;
					}
				}
			}
			return true;
		}

		// Token: 0x040017A8 RID: 6056
		private int _numNodes;

		// Token: 0x040017A9 RID: 6057
		private T[] _nodes;

		// Token: 0x040017AA RID: 6058
		private bool ignoreDebug = true;
	}
}
